package services;

import java.util.Collection;
import java.util.Date;
import java.util.HashSet;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import repositories.RouteRepository;
import domain.Administrator;
import domain.Assess;
import domain.Event;
import domain.Route;
import forms.RouteForm;

@Service
@Transactional
public class RouteService {

	// Managed repository

	@Autowired
	RouteRepository routeRepository;

	// Supporting services
	@Autowired
	EventService eventService;

	@Autowired
	private AdministratorService administratorService;

	// Constructors

	public RouteService() {
		super();
	}

	// Simple CRUD methods

	public Route create(Event event) {

		Collection<Assess> assessment = new HashSet<Assess>();

		Administrator administrator = administratorService.findByPrincipal();

		int orderNumber = event.getRoutes().size() + 1;

		Route result = new Route();

		result.setAdministrator(administrator);
		result.setAssessment(assessment);
		result.setOrderNumber(orderNumber);
		result.setRating(0.0);

		return result;
	}

	public Route findOne(int routeId) {
		Assert.isTrue(routeId != 0);
		Route result;
		result = routeRepository.findOne(routeId);
		Assert.notNull(result);

		return result;
	}

	public Collection<Route> findAllRoutes() {
		Collection<Route> result;
		result = routeRepository.findAll();
		Assert.notNull(result);

		return result;
	}

	public void save(Route route) {
		Assert.notNull(route);

		Assert.isTrue(route.getAdministrator().equals(
				administratorService.findByPrincipal()));
		Date currentMoment = new Date();
		Assert.isTrue(route.getEvent().getStartMoment().after(currentMoment));
		Assert.isTrue(route.getEvent().getRegistrations().isEmpty());

		routeRepository.save(route);
	}

	public void delete(Route route) {
		Assert.isTrue(routeRepository.exists(route.getId()));
		Date currentMoment = new Date();
		Assert.isTrue(route.getEvent().getStartMoment().after(currentMoment));
		Assert.isTrue(route.getEvent().getRegistrations().isEmpty());
		Assert.isTrue(route.getAdministrator().equals(
				administratorService.findByPrincipal()));
		routeRepository.delete(route);
	}

	// Other business methods

	public Collection<Route> findRoutesByAdministrator() {
		Collection<Route> result;
		result = routeRepository.findRoutesByAdministrator(administratorService
				.findByPrincipal().getId());
		Assert.notNull(result);

		return result;
	}

	public Collection<Route> findAllOrderedByRating() {
		Collection<Route> result;
		result = routeRepository.findAllOrderedByRating();
		Assert.notNull(result);
		return result;
	}

	public Collection<Route> findByEventId(int eventId) {
		Collection<Route> result;
		result = routeRepository.findByEventId(eventId);
		Assert.notNull(result);
		return result;
	}

	public Collection<Route> findByAdministratorOrderedByRating(int id) {
		Collection<Route> result;
		result = routeRepository.findByAdministratorOrderedByRating(id);
		Assert.notNull(result);
		return result;
	}

	public Collection<Route> findByParticipantOrderedByRating(int id) {
		Collection<Route> result;
		result = routeRepository.findByParticipantOrderedByRating(id);
		Assert.notNull(result);
		return result;
	}
	
	public Route reconstruct(RouteForm routeForm){
		Event event= eventService.findOne(routeForm.getEventId());
		Route route = create(event);
		route.setName(routeForm.getName());
		route.setLength(routeForm.getLength());
		route.setDifficulty(routeForm.getDifficulty());
		route.setRating(routeForm.getRating());
		route.setEvent(event);
		
		return route;
	}
}
